package com.qumoyugo.springframework.beans.factory;

import com.qumoyugo.springframework.beans.BeansException;
import com.qumoyugo.springframework.beans.PropertyValue;
import com.qumoyugo.springframework.beans.PropertyValues;
import com.qumoyugo.springframework.core.io.DefaultResourceLoader;
import com.qumoyugo.springframework.core.io.Resource;
import com.qumoyugo.springframework.beans.factory.config.BeanDefinition;
import com.qumoyugo.springframework.beans.factory.config.BeanFactoryPostProcessor;
import com.qumoyugo.springframework.util.StringValueResolver;

import java.io.IOException;
import java.util.Properties;

/**
 * @author Cedric
 * @date 2021/12/01 11:19
 * @description 属性占位符配置处理
 */
public class PropertyPlaceHolderConfigurer implements BeanFactoryPostProcessor {

    public static final String DEFAULT_PLACE_HOLDER_PREFIX = "${";
    public static final String DEFAULT_PLACE_HOLDER_SUFFIX = "}";

    private String location;

    public void setLocation(String location) {
        this.location = location;
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        // 加载属性文件
        try {
            DefaultResourceLoader resourceLoader = new DefaultResourceLoader();
            Resource resource = resourceLoader.getResource(location);
            Properties properties = new Properties();
            properties.load(resource.getInputStream());

            String[] beanDefinitionNames = beanFactory.getBeanDefinitionNames();
            for (String beanName : beanDefinitionNames) {
                BeanDefinition beanDefinition = beanFactory.getBeanDefinition(beanName);
                PropertyValues propertyValues = beanDefinition.getPropertyValues();
                for (PropertyValue propertyValue : propertyValues.getPropertyValues()) {
                    Object value = propertyValue.getValue();
                    if (! (value instanceof String)) {
                        continue;
                    }
                    String strVal = resolvePlaceHolder(properties, (String) value);
                    propertyValues.addPropertyValue(new PropertyValue(propertyValue.getName(), strVal));
                }
            }

            // 向容器中添加字符串解析器，共解析@Value使用
            StringValueResolver valueResolver = new PlaceHolderResolvingStringValueResolver(properties);
            beanFactory.addEmbeddedValueResolver(valueResolver);
        } catch (IOException e) {
            throw new BeansException("Cloud not load properties", e);
        }
    }

    private String resolvePlaceHolder(Properties properties, String value) {
        StringBuilder buffer = new StringBuilder(value);

        int startIdx = value.indexOf(DEFAULT_PLACE_HOLDER_PREFIX);
        int stopIdx = value.indexOf(DEFAULT_PLACE_HOLDER_SUFFIX);

        if (startIdx != -1 && stopIdx != -1 && startIdx < stopIdx) {
            String propKey = value.substring(startIdx + 2, stopIdx);
            String propVal = properties.getProperty(propKey);
            buffer.replace(startIdx, stopIdx + 1, propVal);
        }
        return buffer.toString();
    }

    private class PlaceHolderResolvingStringValueResolver implements StringValueResolver {
        private Properties properties;

        public PlaceHolderResolvingStringValueResolver(Properties properties) {
            this.properties = properties;
        }

        @Override
        public String resolveStringValue(String strVal) {
            return PropertyPlaceHolderConfigurer.this.resolvePlaceHolder(properties, strVal);
        }
    }
}
